﻿using PBO.Data;
using PBO.Data.Domain;
using PBO.Network;
using System;
using System.Collections.Generic;
using System.Linq;

namespace PBO.Game.BattleClass
{
    public partial class Pokemon
    {
        public Ability Ability
        {
            get { return GameService.GetAbility(GetSelTrait()); }
        }

        private Trait mSelTrait;

        public Trait GetSelTrait(bool ignoreGastricJuice = false)
        {
            if (BattleState.gastricJuice && !ignoreGastricJuice)
                return Trait.None;
            if (BattleState.worrySeed)
                return Trait.Insomnia;
            if (BattleState.tempTrait != Trait.None)
                return BattleState.tempTrait;
            return mSelTrait;
        }

        public void SetSelTrait(Trait value)
        {
            BattleState.tempTrait = value;
            BattleState.traitRaised = false;
        }

        /// <summary>
        /// 重启特性
        /// </summary>
        public void RaiseTrait()
        {
            if (MyTeam == null) return;

            switch (GetSelTrait())
            {
                case Trait.Intimidate:
                    foreach (Pokemon target in MyTeam.Group.Opponent.SelectedPokemon)
                    {
                        if (!(target.BattleState.substituted || target.HealthPower == 0))
                        {
                            ShowTrait();
                            //MyTeam.log.AppendText(GetNameString() + "的威吓特性发动了！");
                            BattleState.intimidated = true;
                            target.AbilityLvDownChanged(StatType.Atk, this, 1, true);
                        }
                    }
                    break;
                case Trait.Insomnia:
                case Trait.VitalSpirit:
                    if (State == PokemonState.Sleep)
                    {
                        MyTeam.log.AppendMsg("DeSLP", this.GetNameString());
                        //MyTeam.log.AddText(GetNameString() + "醒了过来！");
                        State = PokemonState.No;
                    }
                    break;
                case Trait.Immunity:
                    if (State == PokemonState.Poison || State == PokemonState.Toxin)
                    {
                        MyTeam.log.AppendMsg("DePSN", this.GetNameString());
                        //MyTeam.log.AddText(GetNameString() + "解除了中毒状态！");
                        State = PokemonState.No;
                    }
                    break;
                case Trait.WaterVeil:
                    if (State == PokemonState.Burn)
                    {
                        MyTeam.log.AppendMsg("DeBRN", this.GetNameString());
                        //MyTeam.log.AddText(GetNameString() + "解除了烧伤状态！");
                        State = PokemonState.No;
                    }
                    break;
                case Trait.MagmaArmor:
                    if (State == PokemonState.Freeze)
                    {
                        MyTeam.log.AppendMsg("DeFRZ", this.GetNameString());
                        //MyTeam.log.AddText(GetNameString() + "解冻了！"); 
                        State = PokemonState.No;
                    }
                    break;
                case Trait.Limber:
                    if (State == PokemonState.Paralysis)
                    {
                        MyTeam.log.AppendMsg("DePAR", this.GetNameString());
                        //MyTeam.log.AddText(GetNameString() + "解除了麻痹状态！");
                        State = PokemonState.No;
                    }
                    break;
                case Trait.OwnTempo:
                    if (BattleState.confusion)
                    {
                        MyTeam.log.AppendMsg("DeConfuse", this.GetNameString());
                        //MyTeam.log.AddText(GetNameString() + "解除了混乱！"); 
                        BattleState.confusion = false;
                    }
                    break;
                case Trait.Oblivious:
                    if (BattleState.captivated)
                    {
                        MyTeam.log.AppendMsg("DeAttract", this.GetNameString());
                        //MyTeam.log.AddText(GetNameString() + "解除了着迷状态！");
                        BattleState.captivated = false;
                        BattleState.captivateTarget = null;
                    }
                    break;
                case Trait.Drizzle:
                    ShowTrait();
                    MyTeam.ground.NewWeather(Weather.Rainy, this, MyTeam.log, true);
                    break;
                case Trait.Drought:
                    ShowTrait();
                    MyTeam.ground.NewWeather(Weather.Sunny, this, MyTeam.log, true);
                    break;
                case Trait.SandStream:
                    ShowTrait();
                    MyTeam.ground.NewWeather(Weather.SandStorm, this, MyTeam.log, true);
                    break;
                case Trait.SnowWarning:
                    ShowTrait();
                    MyTeam.ground.NewWeather(Weather.HailStorm, this, MyTeam.log, true);
                    break;
                case Trait.Truant:
                    BattleState.traitRaised = false;
                    break;
                case Trait.Pressure:
                    ShowTrait();
                    MyTeam.log.AppendMsg("Pressure", this.GetNameString());
                    //MyTeam.log.AddText(GetNameString() + "向对手施加了压力！");
                    break;
                case Trait.SlowStart:
                    ShowTrait();
                    MyTeam.log.AppendMsg("EnSlowStart", this.GetNameString());
                    BattleState.slowStartCounter = 5;
                    break;
                case Trait.Hydration:
                    if (State != PokemonState.No && MyTeam.ground.Weather == Weather.Rainy)
                    {
                        ShowTrait();
                        State = PokemonState.No;
                        MyTeam.log.AppendMsg("StateReset", this.GetNameString());
                        //MyTeam.log.AddText(GetNameString() + "的润湿身体特性使它恢复了状态");
                    }
                    break;
                case Trait.NaturalCure:
                    State = PokemonState.No;
                    break;
                case Trait.Multitype:
                    if (64 < (int)GetItem() && (int)GetItem() < 81)
                    {
                        //SetType(1, BattleData.GetTypeData(ModShare.TYPE_INDEX[(int)GetItem() - 64]));
                        SetType(1, (BattleType)((int)GetItem() - 63));
                    }
                    else
                    {
                        SetType(1, BattleType.Normal);
                    }
                    break;
                case Trait.WaterAbsorb:
                    ShowTrait();
                    MyTeam.log.AppendMsg("HpRecover", this.GetNameString());
                    //MyTeam.log.AppendText(GetNameString() + "的蓄水特性吸收了攻击！");
                    this.HPRecoverFraction(4);
                    break;
                case Trait.StormDrain:
                    ShowTrait();
                    //MyTeam.log.AppendMsg("HpRecover", this.GetNameString());
                    //MyTeam.log.AppendText(GetNameString() + "的吸水特性吸收了攻击！");
                    AbilityLvUpChanged(StatType.SpAtk, 1, false);
                    //SAtkLVUp(1, false);
                    break;
                case Trait.DrySkin:
                    ShowTrait();
                    MyTeam.log.AppendMsg("HpRecover", this.GetNameString());
                    //MyTeam.log.AppendText(GetNameString() + "的干燥皮肤特性吸收了攻击！");
                    this.HPRecoverFraction(4);
                    break;
                case Trait.VoltAbsorb:
                    ShowTrait();
                    MyTeam.log.AppendMsg("HpRecover", this.GetNameString());
                    //MyTeam.log.AppendText(GetNameString() + "的蓄电特性吸收了攻击！");
                    this.HPRecoverFraction(4);
                    break;
                case Trait.Lightningrod:
                    ShowTrait();
                    MyTeam.log.AppendMsg("Ability", this.GetNameString(), this.GetSelTrait());
                    //MyTeam.log.AppendText(GetNameString() + "的避雷针特性吸收了攻击！");
                    AbilityLvUpChanged(StatType.SpAtk, 1, false);
                    //SAtkLVUp(1, false);
                    break;
                case Trait.FlashFire:
                    ShowTrait();
                    MyTeam.log.AppendMsg("FlashFire", this.GetNameString());
                    //MyTeam.log.AppendText(GetNameString() + "的引火特性吸收了攻击！");
                    BattleState.traitRaised = true;
                    break;
                case Trait.MotorDrive:
                    ShowTrait();
                    //MyTeam.log.AppendText(GetNameString() + "的电力引擎特性吸收了攻击！");
                    AbilityLvUpChanged(StatType.Speed, 1, false);
                    //SpeedLVUp(1, false);
                    break;
                case Trait.SolarPower:
                    if (MyTeam.ground.Weather == Weather.Sunny)
                    {
                        ShowTrait();
                        MyTeam.log.AppendMsg("Hurt", this.GetNameString());
                        //MyTeam.log.AppendText(GetNameString() + "吸收了阳光的能量！");
                        this.HurtFraction(8);
                    }
                    break;
                case Trait.IceBody:
                    if (MyTeam.ground.Weather == Weather.HailStorm && HealthPower != MaxHp)
                    {
                        ShowTrait();
                        MyTeam.log.AppendMsg("HpRecover", this.GetNameString());
                        //MyTeam.log.AppendText(GetNameString() + "的冰之躯体特性使它回复了HP！");
                        this.HPRecoverFraction(16);
                    }
                    break;
                case Trait.RainDish:
                    if (MyTeam.ground.Weather == Weather.Rainy && HealthPower != MaxHp)
                    {
                        ShowTrait();
                        MyTeam.log.AppendMsg("HpRecover", this.GetNameString());
                        //MyTeam.log.AppendText(GetNameString() + "的接雨盘特性使它回复了HP！");
                        this.HPRecoverFraction(16);
                    }
                    break;
                case Trait.ShedSkin:
                    if (State != PokemonState.No && MyTeam.random.NextDouble() < 0.3)
                    {
                        State = PokemonState.No;
                        ShowTrait();
                        MyTeam.log.AppendMsg("StateReset", this.GetNameString());
                        //MyTeam.log.AddText(GetNameString() + "的蜕皮特性使它恢复了状态");
                    }
                    break;
                case Trait.SpeedBoost:
                    if (SpeedLV < 6 && BattleState.stayOneTurn)
                    {
                        ShowTrait();
                        AbilityLvUpChanged(StatType.Speed, 1, false);
                        //SpeedLVUp(1, false);
                    }
                    break;
                case Trait.AngerPoint:
                    ShowTrait();
                    AbilityLvUpChanged(StatType.Atk, 12, false);
                    //AtkLVUp(12, false);
                    break;
                case Trait.Download:
                    ShowTrait();
                    Pokemon[] targets = MyTeam.Group.Opponent.AliveSelectedPokemon.ToArray();
                    if (targets.Any())
                    {
                        Pokemon target = targets[MyTeam.random.Next(0, targets.Length)];
                        if (target.GetDefence() < target.GetSpDefence())
                        {
                            AbilityLvUpChanged(StatType.Atk, 1, false);
                            //AtkLVUp(1, false);
                        }
                        else if (target.GetDefence() >= target.GetSpDefence())
                        {
                            AbilityLvUpChanged(StatType.SpAtk, 1, false);
                            //SAtkLVUp(1, false);
                        }
                    }
                    break;
                case Trait.Trace:
                    targets = MyTeam.Group.Opponent.AliveSelectedPokemon.ToArray();
                    if (targets.Any())
                    {
                        Pokemon target = targets[MyTeam.random.Next(0, targets.Length)];
                        if (!(target.GetSelTrait(true) == Trait.Forecast) && !(target.GetSelTrait(true) == Trait.Trace))
                        {
                            ShowTrait();
                            MyTeam.log.AppendMsg("SetAbility", this.GetNameString(), target.GetSelTrait(true));
                            //MyTeam.log.AddText(GetNameString() + "复制了" + target.GetNameString() + "的" + target.GetSelTrait(true).ToString() + "特性！");
                            SetTrait(target.GetSelTrait(true));
                        }
                    }
                    break;
                case Trait.Frisk:
                    targets = MyTeam.Group.Opponent.AliveSelectedPokemon.Where(p => p.GetItem() != Item.None).ToArray();
                    if (targets.Any())
                    {
                        Pokemon target = targets[MyTeam.random.Next(0, targets.Length)];
                        ShowTrait();
                        MyTeam.log.AppendMsg("Frisk", this.GetNameString(), target.GetItem());
                        //MyTeam.log.AppendText(GetNameString() + "洞悉到" + target.GetNameString() + "持有" + target.GetItem().ToString() + "！");
                    }
                    break;
                case Trait.Anticipation:
                    targets = MyTeam.Group.Opponent.AliveSelectedPokemon.ToArray();
                    if (targets.Any())
                    {
                        Pokemon target = targets[MyTeam.random.Next(0, targets.Length)];
                        int count = target.GetSelMoves().Count(m =>
                            m.Data.AddEffect2 == MoveAdditionalEffect.必杀 ||
                            m.Data.AddEffect1 == MoveAdditionalEffect.自爆 ||
                            Battle.CalculateAttackTypeEffect(target, this, m.Type) > 1);
                        if (count > 0)
                        {
                            ShowTrait();
                            MyTeam.log.AppendMsg("Anticipation", this.GetNameString());
                            //MyTeam.log.AddText(GetNameString() + "显得很害怕！");
                        }
                    }
                    break;
                case Trait.Forewarn:
                    targets = MyTeam.Group.Opponent.AliveSelectedPokemon.ToArray();
                    if (targets.Any())
                    {
                        Pokemon target = targets[MyTeam.random.Next(targets.Length)];
                        var max_power = target.GetSelMoves().Max(m => m.Power);
                        var max_moves = target.GetSelMoves().Where(m => m.Power == max_power).Select(m => m.Data.Name).ToArray();
                        int count = MyTeam.random.Next(max_moves.Length);
                        ShowTrait();
                        MyTeam.log.AppendMsg("ReadMove", target.GetNameString(), max_moves[count]);
                        //MyTeam.log.AppendText(GetNameString() + "感知到" + target.GetNameString() + "拥有" + max_moves[count] + "技能！");
                    }
                    break;
            }
        }

        public void ShowTrait()
        {
            ShowTrait(this.GetSelTrait());
        }

        private void ShowTrait(Trait trait)
        {
            MyTeam.log.AppendMsg("Ability", this.GetNameString(), trait);
        }

        public void CheckTrait()
        {
            Trait[] array = { Trait.Insomnia, Trait.Immunity, Trait.WaterVeil, Trait.MagmaArmor, Trait.VitalSpirit, Trait.Limber, Trait.OwnTempo, Trait.Oblivious };

            if (array.Contains(this.GetSelTrait()))
            {
                RaiseTrait();
            }
        }

        public void SetTrait(Trait traitValue)
        {
            SetSelTrait(traitValue);
            Trait[] array = { Trait.Intimidate, Trait.SlowStart, Trait.Frisk, Trait.Trace, Trait.Download, Trait.Forewarn, Trait.Anticipation, Trait.Truant, Trait.Pressure, Trait.Multitype };
            if (array.Contains(this.GetSelTrait()))
            {
                RaiseTrait();
            }
            else
            {
                CheckTrait();
            }
        }
    }
}
